package com.gujiayue.module.socket.service.impl;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.gujiayue.common.utils.StringUtils;
import com.gujiayue.module.socket.pojo.SocketMsgDo;
import com.gujiayue.module.socket.service.SocketService;

@Service
public class SocketServiceImpl implements SocketService {

	// 推送的事件
	public static final String PUSH_TYPE = "push_type";

	// 用来存已连接的客户端
	private static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();

	@Resource
	private SocketIOServer socketServer;

	/**
	 * Spring IoC容器创建之后，在加载SocketServiceImpl Bean之后启动
	 */
	@PostConstruct
	private void autoStartup() throws Exception {
		start();
	}

	/**
	 * Spring IoC容器在销毁SocketServiceImpl Bean之前关闭,避免重启项目服务端口占用问题
	 */
	@PreDestroy
	private void autoStop() throws Exception {
		stop();
	}

	@Override
	public void start() {
		// 监听客户端连接
		socketServer.addConnectListener(client -> {
			String loginUserNum = getParamsByClient(client);
			if (loginUserNum != null) {
				clientMap.put(loginUserNum, client);
			}
		});

		// 监听客户端断开连接
		socketServer.addDisconnectListener(client -> {
			String loginUserNum = getParamsByClient(client);
			if (loginUserNum != null) {
				clientMap.remove(loginUserNum);
				client.disconnect();
			}
		});

		// 处理自定义的事件，与连接监听类似
		socketServer.addEventListener(PUSH_TYPE, SocketMsgDo.class, (client, data, ackSend) -> {
			// TODO do something
		});
		
		// 处理自定义的事件，与连接监听类似
		socketServer.addEventListener(PUSH_TYPE, SocketMsgDo.class, (client, data, ackSend) -> {
			// TODO do something
		});

		socketServer.start();
	}

	@Override
	public void stop() {
		if (StringUtils.isNotEmpty(socketServer)) {
			socketServer.stop();
			socketServer = null;
		}
	}

	@Override
	public void pushMessage(SocketMsgDo msgDo) {
		String pushType = msgDo.getPushType();
		if (StringUtils.isNotBlank(pushType)) {
			SocketIOClient client = clientMap.get(pushType);
			if (client != null) {
				client.sendEvent(PUSH_TYPE, msgDo);
			}
		}
	}

	/**
	 * 此方法为获取client连接中的参数，可根据需求更改
	 * 
	 * @return
	 */
	private String getParamsByClient(SocketIOClient client) {
		// 从请求的连接中拿出参数（这里的loginUserNum必须是唯一标识）
		Map<String, List<String>> params = client.getHandshakeData().getUrlParams();
		List<String> list = params.get("pushType");
		if (list != null && list.size() > 0) {
			return list.get(0);
		}
		return null;
	}
}